package es.usc.citius.servando.calendula.util.security;

import android.util.Base64;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import devliving.online.securedpreferencestore.EncryptionManager;

public class LibraryEncryptionProvider implements EncryptionProvider {
    private EncryptionManager encryptionManager;
    private final String TAG = "LibraryEncryptionProv";
    private final String DELIMITER = "]";

    public LibraryEncryptionProvider(EncryptionManager encryptionManager) {
        this.encryptionManager = encryptionManager;
    }

    @Override
    public String encrypt(String value) {
        if(value.isEmpty()){
            throw new IllegalArgumentException("Can't encrypt empty string!");
        }
        byte[] data = value.getBytes(StandardCharsets.UTF_8);
        EncryptionManager.EncryptedData secret = null;
        try {
            secret = encryptionManager.encrypt(data);
        } catch (NoSuchPaddingException | NoSuchAlgorithmException
                | InvalidKeyException | IOException | BadPaddingException
                | NoSuchProviderException | IllegalBlockSizeException
                | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return encodeEncryptedData(secret);
    }

    @Override
    public String decrypt(String value) {
        return null;
    }

    private String base64Encode(byte[] data){
        return Base64.encodeToString(data, Base64.NO_WRAP);
    }

    private byte[] base64Decode(String text){
        return Base64.decode(text, Base64.NO_WRAP);
    }

    private String encodeEncryptedData(EncryptionManager.EncryptedData data) {
        if (data.getMac() != null) {
            return base64Encode(data.getIV()) + DELIMITER + base64Encode(data.getEncryptedData()) + DELIMITER + base64Encode(
                    data.getMac()
            );
        } else {
            return base64Encode(data.getIV()) + DELIMITER + base64Encode(data.getEncryptedData());
        }
    }

    private EncryptionManager.EncryptedData decodeEncryptedText(String text){
        EncryptionManager.EncryptedData result =new EncryptionManager.EncryptedData();
        String[] split = text.split(DELIMITER);
        int index = split.length-1;
        for (int i = split.length-1; i >= 0 ; i--) {
            if (!split[i].isEmpty()){
                index = i;
                break;
            }
        }
        List<String> filter = new ArrayList<>(Arrays.asList(split).subList(0, index));
        String[] parts = (String[]) filter.toArray();
        result.setIV(base64Decode(parts[0]));
        result.setEncryptedData(base64Decode(parts[1]));

        if (parts.length > 2) {
            result.setMac(base64Decode(parts[2]));
        }

        return result;
    }
}
